package com.witframework.remote;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.log4j.Logger;

import com.thoughtworks.xstream.XStream;



/**
 * 简单远程调用请求解析执行类
 * @author wuxinyang
 *
 */
public class RemoteExecutor {
	static Logger logger = Logger.getLogger	( RemoteExecutor.class) ;
	/**
	 * 执行远程调用
	 * @return 返回值对象
	 * @throws RemoteException 在授权验证失败或调用参数错误时	 */
	public static Object invoke(RemoteRequest httpInvokeRequest) throws RemoteException {
		return invoke(httpInvokeRequest,false);
	}
	public static Object invoke(RemoteRequest httpInvokeRequest,boolean resultAsXml) throws RemoteException {
		Object result;
		long startTime=System.currentTimeMillis();
		if(null==httpInvokeRequest)
			throw new RemoteException("not set HttpInvokerRequest.");
		if(httpInvokeRequest.getServerAddress().equals("localhost")){
			result= LocalRequestProcessor.processorLocalhost(httpInvokeRequest);
			if(resultAsXml){
				//result=Java2Xml.toXml(result);				
				result=new XStream().toXML(result);
			}
			return result;
		}
		try {
			RemoteRequest request=(RemoteRequest)httpInvokeRequest.clone();
			request.setResultAsXml(resultAsXml);
			result= processorRemote(request);
		} catch (CloneNotSupportedException e) {
			throw new RemoteException(e);
		}
		long usetime=System.currentTimeMillis()-startTime;
		logger.debug("call remote service completed. used time:"+usetime);
		return result;
	}
	private static Object processorRemote(RemoteRequest httpInvokeRequest) throws RemoteException {
		java.net.HttpURLConnection con=null;
		ObjectOutputStream dataout=null;
		InputStream conis=null;
		OutputStream conos=null;
		ObjectInputStream in=null;
		try {
			URL url = new URL("http://"+httpInvokeRequest.getServerAddress()+"/httpinvoker");
			con = (HttpURLConnection)url.openConnection();
			con.setUseCaches(false);
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setRequestProperty("Content-type", "application/octest-stream");			
			conos=con.getOutputStream();
			dataout = new ObjectOutputStream(conos);
			dataout.writeObject(httpInvokeRequest);
			conis=con.getInputStream();
			in = new ObjectInputStream(conis);
			Object obj = in.readObject();
			if(obj instanceof RuntimeException){
				throw (RuntimeException)obj;
			}
			return obj;
		}catch (ClassNotFoundException e){
			throw new RemoteException(e);
		}catch (IOException e) {			
			throw new RemoteException(e);
		}finally{
			close(in);
			close(conos);
			close(conis);
			close(dataout);
			if(con!=null) con.disconnect();
		}
	}
	private static void close(Closeable object){
		try {
			object.close();
		} catch (Exception e) {
		}
	}
}
